using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace DirkRettschlag.Utils
{
    public static class Invoking
    {

        delegate ListViewItem AddItemCallback(ListView co, ListViewItem item);
        public static ListViewItem AddItem(ListView co, ListViewItem item)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                AddItemCallback d = new AddItemCallback(AddItem);
                return (ListViewItem)co.Invoke(d, new object[] { co, item });
            }
            else
            {
                return co.Items.Add(item);
            }
        }

        delegate void RemoveItemCallback(ListView co, int index);
        public static void RemoveItem(ListView co, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                RemoveItemCallback d = new RemoveItemCallback(RemoveItem);
                co.Invoke(d, new object[] { co, index });
            }
            else
            {
                co.Items.Remove(co.Items[index]);
            }
        }

        delegate bool GetCheckedCallback(CheckBox co);
        public static bool GetChecked(CheckBox co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetCheckedCallback d = new GetCheckedCallback(GetChecked);
                return (bool)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.Checked;                
            }
        }

        delegate bool GetRadioButtonCheckedCallback(RadioButton co);
        public static bool GetRadioButtonChecked(RadioButton co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetRadioButtonCheckedCallback d = new GetRadioButtonCheckedCallback(GetRadioButtonChecked);
                return (bool)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.Checked;
            }
        }

        delegate string GetTextCallback(Control co);
        public static string GetText(Control co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetTextCallback d = new GetTextCallback(GetText);
                return (string)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.Text;
            }

        }

        delegate string GetTabPageNameAtSelectedIndexCallback(TabControl co);
        public static string GetTabPageNameAtSelectedIndex(TabControl co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetTabPageNameAtSelectedIndexCallback d = new GetTabPageNameAtSelectedIndexCallback(GetTabPageNameAtSelectedIndex);
                return (string)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.TabPages[co.SelectedIndex].Name;
            }

        }
              

        delegate void SetTextCallback(Control co, string text);
        public static void SetText(Control co, string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                co.Invoke(d, new object[] { co, text });
            }
            else
            {
                co.Text = text;
            }

        }

        delegate decimal GetValueCallback(NumericUpDown co);
        public static decimal GetValue(NumericUpDown co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetValueCallback d = new GetValueCallback(GetValue);
                return (decimal)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.Value;
            }

        }

        delegate string GetColumnHeaderTextCallback(ListView co, int index);
        public static string GetColumnHeaderText(ListView co, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetColumnHeaderTextCallback d = new GetColumnHeaderTextCallback(GetColumnHeaderText);
                return (string)co.Invoke(d, new object[] { co, index });
            }
            else
            {
                return co.Columns[index].Text;
            }

        }

        delegate void AddListViewItemCallback(ListView co, ListViewItem lvi);
        public static void AddListViewItem(ListView co, ListViewItem lvi)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                AddListViewItemCallback d = new AddListViewItemCallback(AddListViewItem);
                co.Invoke(d, new object[] { co, lvi });
            }
            else
            {
                lock (co)
                    co.Items.Add(lvi);
            }

        }

        delegate void AddComboBoxItemCallback(ComboBox co, string item);
        public static void AddComboBoxItem(ComboBox co, string item)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                AddComboBoxItemCallback d = new AddComboBoxItemCallback(AddComboBoxItem);
                co.Invoke(d, new object[] { co, item });
            }
            else
            {
                lock (co)
                    co.Items.Add(item);
            }

        }

        delegate Control.ControlCollection GetControlsCallback(Control co);
        public static Control.ControlCollection GetControls(Control co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetControlsCallback d = new GetControlsCallback(GetControls);
                return (Control.ControlCollection)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.Controls;
            }

        }

        delegate int GetControlsCountCallback(Control co);
        public static int GetControlsCount(Control co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetControlsCountCallback d = new GetControlsCountCallback(GetControlsCount);
                return (int)co.Invoke(d, new object[] { co });
            }
            else
            {
                return co.Controls.Count;
            }

        }

        delegate Control GetControlAtIndexCallback(Control co, int index);
        public static Control GetControlAtIndex(Control co, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetControlAtIndexCallback d = new GetControlAtIndexCallback(GetControlAtIndex);
                return (Control)co.Invoke(d, new object[] { co, index });
            }
            else
            {
                return co.Controls[index];
            }

        }

        delegate string GetStringPropertyCallback(Control co, string property);
        public static string GetStringProperty(Control co, string property)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                GetStringPropertyCallback d = new GetStringPropertyCallback(GetStringProperty);
                return (string)co.Invoke(d, new object[] { co, property });
            }
            else
            {
                PropertyInfo propertyInfo = co.GetType().GetProperty(property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

                return (string)propertyInfo.GetValue(co, null);
            }

        }

        delegate void AddControlCallback(Control co, Control child);
        public static void AddControl(Control co, Control child)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                AddControlCallback d = new AddControlCallback(AddControl);
                co.Invoke(d, new object[] { co, child });
            }
            else
            {
                //http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669450&SiteID=1
                co.Controls.Add(child);
            }
        }

        delegate void RemoveControlAtIndexCallback(Control co, int index);
        public static void RemoveControlAtIndex(Control co, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                RemoveControlAtIndexCallback d = new RemoveControlAtIndexCallback(RemoveControlAtIndex);
                co.Invoke(d, new object[] { co, index });
            }
            else
            {
                Control removedCo = co.Controls[index];
                co.Controls.RemoveAt(index);
                removedCo.Dispose();
            }
        }

        delegate void HideControlAtIndexCallback(Control co, int index);
        public static void HideControlAtIndex(Control co, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                HideControlAtIndexCallback d = new HideControlAtIndexCallback(HideControlAtIndex);
                co.Invoke(d, new object[] { co, index });
            }
            else
            {
                co.Controls[index].Visible = false;
            }
        }

        delegate void SetControlChildIndexCallback(Control co, Control child, int index);
        public static void SetControlChildIndex(Control co, Control child, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetControlChildIndexCallback d = new SetControlChildIndexCallback(SetControlChildIndex);
                co.Invoke(d, new object[] { co, child, index });
            }
            else
            {
                 co.Controls.SetChildIndex(child, index);
            }
        }

        delegate void SetControlVisibleCallback(Control co, bool visible);
        public static void SetControlVisible(Control co, bool visible)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetControlVisibleCallback d = new SetControlVisibleCallback(SetControlVisible);
                co.Invoke(d, new object[] { co, visible });
            }
            else
            {
                co.Visible = visible;
            }
        }

        delegate void SetControlEnabledCallback(Control co, bool enabled);
        public static void SetControlEnabled(Control co, bool enabled)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetControlEnabledCallback d = new SetControlEnabledCallback(SetControlEnabled);
                co.Invoke(d, new object[] { co, enabled });
            }
            else
            {
                co.Enabled = enabled;
            }
        }

        delegate void SetMenuItemEnabledCallback(Control co, MenuItem mni, bool enabled);
        public static void SetMenuItemEnabled(Control co, MenuItem mni, bool enabled)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetMenuItemEnabledCallback d = new SetMenuItemEnabledCallback(SetMenuItemEnabled);
                co.Invoke(d, new object[] { co, mni, enabled });
            }
            else
            {
                mni.Enabled = enabled;
            }
        }
        
        delegate void SetSelectedIndexCallback(ComboBox co, int index);
        public static void SetSelectedIndex(ComboBox co, int index)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetSelectedIndexCallback d = new SetSelectedIndexCallback(SetSelectedIndex);
                co.Invoke(d, new object[] { co, index });
            }
            else
            {
                co.SelectedIndex = index;
            }
        }
        
        delegate void SetControlLayoutModeCallback(Control co, bool suspend);
        public static void SetControlLayoutMode(Control co, bool suspend)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetControlLayoutModeCallback d = new SetControlLayoutModeCallback(SetControlLayoutMode);
                co.Invoke(d, new object[] { co, suspend });
            }
            else
            {
                if (suspend)
                    co.SuspendLayout();
                else
                    co.ResumeLayout(true);
            }
        }

        delegate void RefreshControlCallback(Control co);
        public static void RefreshControl(Control co)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                RefreshControlCallback d = new RefreshControlCallback(RefreshControl);
                co.Invoke(d, new object[] { co });
            }
            else
            {
                co.Refresh();
            }
        }

        delegate void SetCursorCallback(Control co, Cursor newCursor);
        public static void SetCursor(Control co, Cursor newCursor)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (co.InvokeRequired)
            {
                SetCursorCallback d = new SetCursorCallback(SetCursor);
                co.Invoke(d, new object[] { co, newCursor });
            }
            else
            {
                Cursor.Current = newCursor;
            }
        }

    }
}
